package controller.supplier;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;


import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import utils.file.FileUploadForm;
import utils.product.ProductUploadForm;
import utils.product.ProductEditForm;
import cultu.common.message.User;
import cultu.common.message.UserScenario;
import cultu.common.service.UserManager;
import cultu.community.message.Community;
import cultu.community.service.CommunityManager;
import cultu.community.message.CommunityCriteria;
import cultu.community.message.CommunityList;
import cultu.community.message.CommunityScenario;
import cultu.community.service.CommunityService;
import cultu.core.message.Context;
import cultu.supplier.message.Media;
import cultu.supplier.message.Product;
import cultu.supplier.message.ProductCriteria;
import cultu.supplier.message.ProductList;
import cultu.supplier.message.ProductScenario;
import cultu.supplier.message.Supplier;
import cultu.supplier.message.SupplierScenario;
import cultu.supplier.service.ProductIntegration;
import cultu.supplier.service.ProductManager;
import cultu.supplier.service.ProductService;
import cultu.supplier.service.SupplierManager;
import cultu.supplier.service.impl.ProductIntegrationImpl;
import cultu.utils.CultuUtils;



/**
 * The Class SupplierController.
 */
@Controller
@SessionAttributes({"connectedUser"})
public class SupplierController
{

	/** The Constant LOG. */
	private static final Log LOG = LogFactory.getLog(ProductIntegrationImpl.class);

	/**
	 * The community service.
	 */
	@Autowired
	CommunityService communityService;

	/**
	 * The product service.
	 */
	@Autowired
	ProductService productService;

	/** The product integration service. */
	@Autowired
	ProductIntegration productIntegration;


	/** The user manager. */
	@Autowired
	ProductManager productManager;

	/** The user manager. */
	@Autowired
	CommunityManager communityManager;

	/**
	 * User manager.
	 */
	@Autowired
	UserManager userManager;

	/**
	 * Supplier manager.
	 */
	@Autowired
	SupplierManager supplierManager;

	/**
	 * The first view.
	 *
	 * @param model the model
	 * @return the model and view
	 */


	/**
	 * Data for layout method.
	 * @param modelMap the model map.
	 * @param modelAndView the model and view.
	 */
	public void dataForLayout(final ModelMap modelMap, final ModelAndView modelAndView) {

		if (modelMap != null) {

		}

		if (modelAndView != null) {
			// Put communities css classes.
			modelAndView.addObject("communitiesCSS", CultuUtils.communitiesCSSClasses());

			// Get universe list.
			final CommunityList communityList = communityService.getUniverses(new CommunityScenario(), new CommunityCriteria());
			modelAndView.addObject("universesList", communityList);
		}
	}

	/**
	 * dashboard
	 * @param model
	 * @return ModelAndView
	 */
	@RequestMapping(value="/supplier",method=RequestMethod.GET)
	public ModelAndView dashboard(ModelMap model)
	{
		ModelAndView view = new ModelAndView("supplier-accueil");

		return view;
	}

	/**
	 * getConnectedUser
	 * @return User
	 */
	@ModelAttribute(value="connectedUser")
	public User getConnectedUser()
	{
		User result = null;

		Authentication auth = SecurityContextHolder.getContext().getAuthentication();

		if(auth != null && auth.getName() != null && !"".equals(auth.getName()))
		{
			User user = new User();
			user.setLogin(auth.getName());
			result = userManager.getUser(null, null, user);
		}

		return result;
	}

	/**
	 * Supplier products.
	 *
	 * @param model the model
	 * @return the model and view
	 */
	@RequestMapping(value="/supplier/products",method=RequestMethod.GET)
	public ModelAndView supplierProducts(ModelMap model)
	{
		ModelAndView view = new ModelAndView("supplier-products");


		// Get all communities.
		final CommunityList communitiesList = communityService.findRegistrationCommunities(new CommunityScenario(), new CommunityCriteria());    
		view.addObject("communitiesList", communitiesList.getCommunities());

		return view;
	}

	/**
	 * product
	 * @param model
	 * @param productId
	 * @return ModelAndView
	 */
	@RequestMapping(value="/supplier/product/{productId}", method=RequestMethod.GET)
	public ModelAndView product(ModelMap model, @PathVariable String productId)
	{
		final ModelAndView homePageModel = new ModelAndView("product-details-supplier");

		// Get data for layout.
		dataForLayout(model, homePageModel);

		// Get product.
		Product product = null;
		try {
			product = productService.getProductById(Long.valueOf(productId));
		} catch (Exception e) {

		}

		// Bind product object.
		homePageModel.addObject("product", product);

		return homePageModel;
	}

	/**
	 * Stats products.
	 *
	 * @param model the model
	 * @return the model and view
	 */
	@RequestMapping(value="/supplier/stats",method=RequestMethod.GET)
	public ModelAndView statsProducts(ModelMap model)
	{
		ModelAndView view = new ModelAndView("supplier-stats");
		return view;
	}

	/**
	 * consultProducts
	 * @param model
	 * @return ModelAndView
	 */
	@RequestMapping(value="/supplier/productList", method=RequestMethod.GET)
	public ModelAndView consultProducts(ModelMap model){
		ModelAndView view = new ModelAndView("supplier-consult-products");

		//ProductList productList = productManager.findProductsNative(new Context(), new ProductScenario(), new ProductCriteria());
		ProductScenario pScenario = new ProductScenario();
		pScenario.setManageMedias(true);
		ProductList bestProductsList = productService.getPopularProductsByCommunity(null, pScenario, new ProductCriteria());
		SupplierScenario scenario = new SupplierScenario();
		scenario.setManageProducts(Boolean.TRUE);
		Supplier supplier = getConnectedUser().getSupplier();
		supplier = supplierManager.getSupplier(null, scenario, supplier);


		view.addObject("bestProductsList", supplier.getProducts());

		return view;
	}

	/**
	 * Save.
	 *
	 * @param uploadForm the upload form
	 * @param map the map
	 * @return the model and view
	 */
	@RequestMapping(value = "/supplier/integrate", method = RequestMethod.POST)
	public ModelAndView save(@ModelAttribute("uploadForm") FileUploadForm uploadForm,
			Model map) {

		ModelAndView success = new ModelAndView("integrate-succeed");
		ModelAndView fail = new ModelAndView("integrate-failed");

		MultipartFile multipartFile = uploadForm.getFile();

		String fileName = "";
		byte[] byteArr = null;
		try {
			byteArr = multipartFile.getBytes();
		} catch (IOException e1) {
			return fail;
		}

		if (multipartFile != null) {
			fileName = multipartFile.getOriginalFilename();
			if (fileName.equals("") || fileName == null){
				return fail;
			}
		}

		map.addAttribute("files", fileName);
		productIntegration.integrateFile(byteArr, getConnectedUser().getSupplier());

		return success;
	}

	/**
	 * Adds the product.
	 *
	 * @param productForm the product form
	 * @param map the map
	 * @return the model and view
	 */
	@RequestMapping(value = "/supplier/addProduct", method = RequestMethod.POST)
	public ModelAndView addProduct(@ModelAttribute("productForm") ProductUploadForm productForm,
			Model map) {
		MultipartFile fileToDownload = productForm.getFile();
		ModelAndView success = new ModelAndView("integrate-succeed");
		ModelAndView fail = new ModelAndView("integrate-failed");

		Product product = new Product();
		product.setLabel(productForm.getLabelProduct());

		if (product.getLabel().equals("")){
			return fail;
		}

		product.setCode(productForm.getCodeProduct());
		product.setDescription(productForm.getDescriptionProduct());
		product.setPrice(productForm.getPriceProduct());
		product.setSupplierId(getConnectedUser().getSupplier().getHjid());
		if (productForm.getStockProduct() == 0){
			product.setStockable(false);
		}
		else {
			product.setStockable(true);
			product.setStock(productForm.getStockProduct());
		}

		product.setKeywords(productForm.getKeywordsProduct());
		product.setDownloadPath(fileToDownload.getOriginalFilename());


		Community community = new Community();
		community.setUniverseCode(productForm.getUniverseCommunity());
		community.setCategoryCode(productForm.getCategoryCommunity());
		community.setFamilyCode(productForm.getFamilyCommunity());
		community.setKindCode(productForm.getKindCommunity());


		Media media = new Media();
		media.setMain(true);
		media.setMediaType(productForm.getTypeMedia());
		media.setUrl(productForm.getUrlMedia());


		byte[] byteArr = null;
		try {
			byteArr = fileToDownload.getBytes();
		} catch (IOException e1) {
			LOG.info(e1.getMessage(), e1);
			return fail;
		}

		if (productIntegration.integrateProduct(product, community, media, fileToDownload.getOriginalFilename(), byteArr)){
			return success;
		}
		return fail;
	}

	/**
	 * editProduct
	 * @param editForm
	 * @param map
	 * @return ModelAndView
	 */
	@RequestMapping(value = "/supplier/product/{productId}/edit", method = RequestMethod.POST)
	public ModelAndView editProduct(ModelMap model, @PathVariable String productId) {
		ModelAndView view = new ModelAndView("product-edition-supplier");

		// Get data for layout.
		dataForLayout(model, view);

		// Get product.
		Product product = null;
		try {
			product = productService.getProductById(Long.valueOf(productId));
		} catch (Exception e) {

		}

		// Bind product object.
		view.addObject("product", product);

		return view;
	}

	/**
	 * Edits the product.
	 *
	 * @param editForm the edit form
	 * @param model the model
	 * @return the model and view
	 */
	@RequestMapping(value = "/supplier/product/edition", method = RequestMethod.POST)
	public ModelAndView editProduct(@ModelAttribute("editForm") ProductEditForm editForm, ModelMap model) {
		ModelAndView view = new ModelAndView("supplier-accueil");
		Product p = new Product();
		p.setHjid(editForm.getProductID());
		Product product = productManager.getProduct(null, null, p);


		product.setLabel(editForm.getLabelProduct());
		product.setDescription(editForm.getDescriptionProduct());
		product.setPrice(editForm.getPriceProduct());
		product.setKeywords(editForm.getKeywordsProduct());
		product.setCode(editForm.getCodeProduct());

		productManager.updateProduct(null, null, product);

		return view;
	}	




}
